﻿// -----------------------------------------------------------------------
// <copyright file="BattleField.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Cspl.AnimalFight.Lib
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Cspl.AnimalFight.Lib.Data;
    using Cspl.AnimalFight.Lib.EventHandlers;
    using Cspl.AnimalFight.Lib.Interfaces;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class BattleField
    {
        #region Fields

        private IList<AnimalBase> _animals;

        #endregion

        #region Properties

        public IList<AnimalBase> Animals
        {
            get { return _animals; }
            private set { _animals = value; }
        }

        #endregion

        #region Constructors

        public BattleField()
        {
            this._animals = new List<AnimalBase>();
        }

        #endregion

        #region Methods

        public AnimalBase this[string name]
        {
            get { return this._animals.FirstOrDefault(a => a.Name == name); }
            set
            {
                if (value != null)
                {
                    IAttack attackingAnimal = value as IAttack;
                    if (attackingAnimal != null)
                    {
                        attackingAnimal.AttackEvent += new AttackDelegate(attackingAnimal_AttackEvent);
                    }

                    IDefend defendingAnimal = value as IDefend;
                    if (defendingAnimal != null)
                    {
                        defendingAnimal.DefendEvent += new DefendDelegate(defendingAnimal_DefendEvent);
                    }

                    this._animals.Add(value);
                }
            }
        }

        private void defendingAnimal_DefendEvent(object sender, DefendEventHandler e)
        {
            var defendingAnimal = this[e.AnimalName];

            if (defendingAnimal != null)
            {
                IDefend theAnimal = defendingAnimal as IDefend;
                if (theAnimal != null)
                {
                    theAnimal.IsDefending = true;
                    //to show defend status
                    Console.WriteLine("  The animal {0} is defend.", e.AnimalName);
                }
                else
                {
                    //to solve when defending animal does not exist
                    Console.WriteLine("  The animal {0} cannot defend itself.", e.AnimalName);
                }
            }
            else {
                Console.WriteLine("  The animal {0} is does not exist.", e.AnimalName);
            }
        }

        private void attackingAnimal_AttackEvent(object sender, AttackEventHandler e)
        {
            var animalTarget = this[e.AnimalTargetName];

            if (animalTarget != null)
            {
                IAttackable attackedAnimal = animalTarget as IAttackable;
                if (attackedAnimal != null)
                {
                    Console.WriteLine("  {0} is attacked with AP={1}.", e.AnimalTargetName, e.AP);
                    Console.WriteLine("  {0} DP is {1}. ", e.AnimalTargetName, animalTarget.DP);
                    attackedAnimal.Attacked(e.AP);
                }
                else
                {
                    Console.WriteLine("  The animal {0} is immortal.", e.AnimalTargetName);
                }
            }
            // to solve bug when attacked animal not found
            else
            {
               Console.WriteLine("  Animal {0} is not exists.", e.AnimalTargetName);
            }
        }

        public void Command(string animalName, Commands command, string targetName)
        {
            var animal = this[animalName];
            var target = this[targetName];

            if (animal != null)
            {
                if (!animal.IsDead)
                {
                    switch (command)
                    {
                        case Commands.Attack:
                            if (animal != target)
                            {
                                //check if the animal can attack
                                if (!animal.HasEscaped)
                                {
                                    if (animal is IAttack)
                                    {
                                        (animal as IAttack).Attack(targetName);
                                    }
                                    else
                                    {
                                        Console.WriteLine("  Animal {0} cannot attack. It doesn't have Attack Ability.", animalName);
                                    }
                                }
                                else
                                {
                                    //to show if the animal has escaped it cannot attacked
                                    Console.WriteLine("  Animal {0} has escaped, cannot attack.", animalName);
                                }                            
                            }
                            else
                            {
                                Console.WriteLine("  Animal {0} cannot attack itself.", animalName);
                            }
                            break;

                        case Commands.Defend:
                            //Check if animal can defend
                            if (animal != target)
                            {
                                if (!animal.HasEscaped)
                                {
                                    if (animal is IDefend)
                                    {
                                        (animal as IDefend).Defend();
                                    }
                                    else
                                    {
                                        Console.WriteLine("  Animal {0} cannot defend. It doesn't have Defense Ability.", animalName);
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("  Animal {0} has escaped, cannot defend.", animalName);
                                }
                            }
                            else
                            {
                                Console.WriteLine("  Animal {0} cannot defend itself.", animalName);
                            }                         
                            break;

                        case Commands.Escape:
                            //check if animal is dead or not
                            if (!animal.IsDead)
                            {
                                animal.Escape();
                            }
                            else 
                            {
                                Console.WriteLine("  Animal {0} is already dead, cannot escaped.", animalName);
                            }
                            break;

                        case Commands.Return:
                            //check if animal is escape or not
                            if (animal.HasEscaped)
                            {
                                animal.Return();
                            }
                            else
                            {
                                Console.WriteLine("  Animal {0} is already join the Battlefield.", animalName);
                            }
                            break;
                    }
                }
                else
                {
                    Console.WriteLine("  Animal {0} is dead.", animalName);
                }               
            }
            else
            {
                Console.WriteLine("  Animal {0} is not exists.", animalName);
            }
        }

        public void AnimalStatus()
        {
            Console.WriteLine("Animal Name \tAP \tDP \tHP \tDead? \tEscape? \tReturn?");
            Console.WriteLine("----------------------------------------------------------------------------");
            foreach (AnimalBase anim in Animals)
            {
                Console.WriteLine("  {0} \t{1} \t{2} \t{3} \t{4} \t{5} \t\t{6}", anim.Name, anim.AP, anim.DP, anim.HP, anim.IsDead, anim.HasEscaped, anim.HasReturned);
            }
            Console.WriteLine("");
        }

        public void displayCommand()
        {
            Console.WriteLine();
            Console.WriteLine("Commands (non case sensitive):");
            Console.WriteLine();
            Console.WriteLine("  Add [typeAnimal][AnimalName][HealthPower][DefensePower][AttackPower]");
            Console.WriteLine("  ---> Example1: Add Snake Sanca 1000 100 300 <---");
            Console.WriteLine("  ---> Example2: add Snake Cobra 1000 200 300 <---");
            Console.WriteLine();
            Console.WriteLine("  Upgrade [AnimalName][typePower][PowerValue]");
            Console.WriteLine("  ---> Example: Upgrade Doggy AP 150 <---");
            Console.WriteLine();
            Console.WriteLine("  Attack [animalAttack][AnimalTarget] \tExample1: Attack Snake Snoopy");
            Console.WriteLine("  Attack [animalAttack][AnimalTarget] \tExample2: attack Snake Snoopy");
            Console.WriteLine("  Defend [animalName] \t\t\tExample: Defend Snake");
            Console.WriteLine("  Escape [animalName] \t\t\tExample: Escape Snake");
            Console.WriteLine("  Return [animalName] \t\t\tExample: Return Snake");
            Console.WriteLine("  Status \t(s or S as shortcut)\tto View Animal Status");
            Console.WriteLine("  Exit \t\t(x as shortcut) \tto Exit the Application\n");

        }

        public void addAnimal(string animal, string name, int hp, int dp, int ap)
        {
            if (name != "")
            {
                switch (animal)
                {
                    case "Dog":
                        Dog dog1 = new Dog
                        {
                            Name = name,
                            HP = hp,
                            DP = dp,
                            AP = ap
                        };
                        this[dog1.Name] = dog1;
                        Console.WriteLine("  Add animal {0} SUCCESS.", name);
                        break;
                    case "Duck":
                        Duck duck1 = new Duck
                        {
                            Name = name,
                            HP = hp,
                            DP = dp,
                            AP = ap
                        };
                        this[duck1.Name] = duck1;
                        Console.WriteLine("  Add animal {0} SUCCESS.", name);
                        break;
                    case "Snake":
                        Snake snake1 = new Snake
                        {
                            Name = name,
                            HP = hp,
                            DP = dp,
                            AP = ap,
                        };
                        this[snake1.Name] = snake1;
                        Console.WriteLine("  Add animal {0} SUCCESS.", name);
                        break;
                    case "Horse":
                        Horse horse1 = new Horse
                        {
                            Name = name,
                            HP = hp,
                            DP = dp,
                            AP = ap,
                        };
                        this[horse1.Name] = horse1;
                        Console.WriteLine("  Add animal {0} SUCCESS.", name);
                        break;
                    default:
                        Console.WriteLine("  Add animal {0} FAILED. {1} type not exist", name, animal);
                        break;
                }
            }
            else
            {
                Console.WriteLine("  Please input animal Name. ");
            }           
        }


        public void upgradePower(string animalName, string power, string powervalue)
        {
            var animal = this[animalName];
            if (animalName != "")
            {
                if (!animal.IsDead)
                {
                    if ((animal is Dog) && (power == "Mood"))
                    {
                        upgradeMood(animalName, powervalue);
                    }
                    else
                    {
                        int val = Convert.ToInt32(powervalue);
                        switch (power)
                        {
                            case "HP":
                                animal.HP = val;
                                Console.WriteLine("  Upgrade {0} HP = {1} SUCCESS.", animalName, val);
                                break;
                            case "AP":
                                animal.AP = val;
                                Console.WriteLine("  Upgrade {0} AP = {1} SUCCESS.", animalName, val);
                                break;
                            case "DP":
                                animal.DP = val;
                                Console.WriteLine("  Upgrade {0} DP = {1} SUCCESS.", animalName, val);
                                break;
                            default:
                                Console.WriteLine("  Upgrade {0} Failed. Please choose the right power.", animal);
                                break;
                        }
                    }
                }
                else
                {
                    Console.WriteLine("  {0} is dead, cannot upgrade power.", animalName);
                }
            }
            else
            {
                Console.WriteLine("  Please input animal name.");
            }
        }

        public void upgradeMood(string animalName, string val)
        {
            var animal = this[animalName];
            if (animalName != "")
            {
                if (!animal.IsDead)
                {
                    switch (val)
                    {
                        case "Good":
                            (animal as Dog).Mood = DogMood.Good;
                            Console.WriteLine("  {0} upgrade mood SUCCESS.", animalName);
                            break;
                        case "Bad":
                            (animal as Dog).Mood = DogMood.Bad;
                            Console.WriteLine("  {0} upgrade mood SUCCESS.", animalName);
                            break;
                        default:
                            Console.WriteLine("  Please input right mood value.");
                            break;
                    }
                }
                else
                {
                    Console.WriteLine("  {0} is dead, cannot upgrade power.", animalName);
                }
            }
            else
            {
                Console.WriteLine("  Please input animal name.");
            }
        }

        #endregion
       
    }

    public enum Commands { Attack, Defend, Escape, Return }
}
